home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_500 / wiconify / wiconsetter.lzh / wIconSetter / Source / wIconSetter.c < prev    next >
C/C++ Source or Header  |  1991-04-19  |  16KB  |  591 lines

  1. /*
  2.  *  WICONSETTER     A companion utility to wIconify.  wIconSetter allows
  3.  *                  you to specify custom icons for windows ans screens
  4.  *                  that normally use the default icons.
  5.  *
  6.  *  wIconSetter.c   Main loader code for wIconSetter.
  7.  *
  8.  *  Copyright 1990 by Davide P. Cervone, all rights reserved.
  9.  *  You may use this code, provided this copyright notice is kept intact.
  10.  */
  11.  
  12. #include "wIconSetter.h"
  13.  
  14. static char *program   = PROGRAM;
  15. static char *copyright = COPYRIGHT; 
  16.  
  17. static char *handler   = HANDLERCODE;       /* The name of the handler file */
  18. #define HANDLER          &(handler[2])      /* Handler without the L: */
  19.  
  20. static struct IconHandlerInfo *IconHandlerData;
  21. static long Segment;                        /* The loaded handler segment */
  22.  
  23. ICONPROGRAM *FirstProgram;                  /* The list of icons */
  24. ICONPROGRAM *ProgramAny;                    /* the program named [ANY] */
  25. ICONDEFINE  *FirstDefine;                   /* the list of defined icons */
  26.  
  27.  
  28.  
  29. /*
  30.  *  PrefixMatch()
  31.  *
  32.  *  Calls the handler's PrefixMatch routine, after checking
  33.  *  for NAME_ANY matches.
  34.  */
  35.  
  36. int PrefixMatch(s1,s2)
  37. char *s1,*s2;
  38. {
  39.    if (s1 == NAME_ANY) return(s2 == NAME_ANY); else
  40.    if (s2 == NAME_ANY) return(1);
  41.  
  42.    return(VAR(PrefixMatch)(s1,s2));
  43. }
  44.  
  45.  
  46. /*
  47.  *  FreeImage()
  48.  *
  49.  *  If an image structure was given,
  50.  *    If the image has allocated data, free it
  51.  *    Free the image structure itself
  52.  */
  53.  
  54. void FreeImage(theImage)
  55. struct Image *theImage;
  56. {
  57.    if (theImage)
  58.    {
  59.       if (theImage->ImageData) FreeRaster(theImage->ImageData,
  60.          theImage->Width,theImage->Height*theImage->Depth);
  61.       FREESTRUCT(Image,theImage);
  62.    }
  63. }
  64.  
  65.  
  66. /*
  67.  *  FreeWindow()
  68.  *
  69.  *  Free any images associated with the window
  70.  *  Free the window's icon's name, if any
  71.  *  Free the window's name, if any
  72.  *  Free the window structure itself
  73.  */
  74.  
  75. void FreeWindow(theWindow)
  76. ICONWINDOW *theWindow;
  77. {
  78.    if (theWindow->Flags & IW_IMAGE)   FreeImage(theWindow->Icon.Image);
  79.    if (theWindow->Flags & IW_SELECT)  FreeImage(theWindow->Icon.Select);
  80.    if (theWindow->Flags & IW_MASK)    FreeImage(theWindow->Mask);
  81.    if (theWindow->Flags & IW_NAME)    FREECHAR(theWindow->Icon.Name);
  82.    if (theWindow->Name != NAME_NULL && theWindow->Name != NAME_ANY &&
  83.        theWindow->Name != SCREENICON) FREECHAR(theWindow->Name);
  84.    FREESTRUCT(IconWindow,theWindow);
  85. }
  86.  
  87.  
  88. /*
  89.  *  FreeScreen()
  90.  *
  91.  *  While the screen has more windows
  92.  *    Free the window and move on to the next one
  93.  *  Free the screen's name, if any
  94.  *  Free the screen structure itself
  95.  */
  96.  
  97. void FreeScreen(theScreen)
  98. ICONSCREEN *theScreen;
  99. {
  100.    ICONWINDOW *nextWindow;
  101.    
  102.    while (theScreen->Window)
  103.    {
  104.       nextWindow = theScreen->Window->Next;
  105.       FreeWindow(theScreen->Window);
  106.       theScreen->Window = nextWindow;
  107.    }
  108.    if (theScreen->Name != NAME_NULL && theScreen->Name != NAME_ANY)
  109.       FREECHAR(theScreen->Name);
  110.    FREESTRUCT(IconScreen,theScreen);
  111. }
  112.  
  113.  
  114. /*
  115.  *  FreeProgram()
  116.  *
  117.  *  While there are more screens associated with this program
  118.  *    Free the screen and move on to the next one
  119.  *  Free the program's name, if any
  120.  *  Free the program structure itself
  121.  */
  122.  
  123. void FreeProgram(theProg)
  124. ICONPROGRAM *theProg;
  125. {
  126.    ICONSCREEN *nextScreen;
  127.    
  128.    while (theProg->Screen)
  129.    {
  130.       nextScreen = theProg->Screen->Next;
  131.       FreeScreen(theProg->Screen);
  132.       theProg->Screen = nextScreen;
  133.    }
  134.    if (theProg->Name != NAME_NULL && theProg->Name != NAME_ANY)
  135.       FREECHAR(theProg->Name);
  136.    FREESTRUCT(IconProgram,theProg);
  137. }
  138.  
  139.  
  140. /*
  141.  *  FreeLists()
  142.  *
  143.  *  Convert the binary tree back into a linked list
  144.  *  While there are programs in the list
  145.  *    Free the program and move on to the next one
  146.  *  If there is a ProgramAny, free it
  147.  *  While there are more definitions in the list
  148.  *    Free the definition and move on to the next one
  149.  */
  150.  
  151. static void FreeLists()
  152. {
  153.    ICONPROGRAM *nextProg;
  154.    ICONDEFINE  *nextDefine;
  155.    extern ICONPROGRAM *TreeToList();
  156.    
  157.    FirstProgram = TreeToList(FirstProgram);
  158.    while (FirstProgram)
  159.    {
  160.       nextProg = FirstProgram->Next;
  161.       FreeProgram(FirstProgram);
  162.       FirstProgram = nextProg;
  163.    }
  164.    if (ProgramAny) FreeProgram(ProgramAny);
  165.    
  166.    while (FirstDefine)
  167.    {
  168.       nextDefine = FirstDefine->Next;
  169.       FreeDefine(FirstDefine);
  170.       FirstDefine = nextDefine;
  171.    }
  172. }
  173.  
  174.  
  175. /*
  176.  *  DoExit()
  177.  *
  178.  *  General purpose error-exit routine.  Print an error message if one was
  179.  *  supplied (it can have up to three parameters), and then clean up any
  180.  *  memory, libraries, etc. that need to be handled before exiting.
  181.  */
  182.  
  183. void DoExit(s,x1,x2,x3)
  184. char *s, *x1, *x2, *x3;
  185. {
  186.    long status = EXIT_OK;
  187.    
  188.    if (s != NULL)
  189.    {
  190.       printf(s,x1,x2,x3);
  191.       printf("\n");
  192.       status = EXIT_ERROR;
  193.    }
  194.    FreeLists();
  195.    if (Segment)         UnLoadSeg(Segment);
  196.    if (IntuitionBase)   CloseLibrary(IntuitionBase);
  197.    if (GfxBase)         CloseLibrary(GfxBase);
  198.    exit(status);
  199. }
  200.  
  201.  
  202. /*
  203.  *  CheckLibOpen()
  204.  *
  205.  *  Call OpenLibrary() for the specified library, and check that the 
  206.  *  open succeeded.
  207.  */
  208.  
  209. static void CheckLibOpen(lib,name,rev)
  210. APTR *lib;
  211. char *name;
  212. int rev;
  213. {
  214.    extern APTR OpenLibrary();
  215.  
  216.    if ((*lib = OpenLibrary(name,(LONG)rev)) == NULL)
  217.       DoExit("Can't open %s",name);
  218. }
  219.  
  220.  
  221. /*
  222.  *  LoadHandler()
  223.  *
  224.  *  Try to LoadSeg the handler from the current directory, and if it is not
  225.  *  found, try the L: directory.  If neither can be loaded, exit with an
  226.  *  error message.  Once the handler is loaded, call the Setup routine
  227.  *  in the handler code and pass the loader version number.  The handler will
  228.  *  check the version for compatibility and returns NULL if there is a
  229.  *  mismatch, or a pointer to the shared data if everything is OK.
  230.  *  Check the handler version number, and then store the loader version
  231.  *  and the segment list pointer for use in unloading the handler later.
  232.  *  The MsgPort is the first item in the IconHandlerInfo structure.  It is used
  233.  *  to link the information into the system port list, where we can find it
  234.  *  later.
  235.  */
  236.  
  237. void LoadHandler(thePort)
  238. struct MsgPort **thePort;
  239. {
  240.    struct IconHandlerInfo *(*Setup)();
  241.    
  242.    if ((Segment = LoadSeg(HANDLER)) == NULL)
  243.       if ((Segment = LoadSeg(handler)) == NULL)
  244.          DoExit("Can't load %s",handler);
  245.    Setup = (struct IconHandlerInfo *(*)()) ((Segment << 2) + 4);
  246.    
  247.    IconHandlerData = (*Setup)(LOADVERS);
  248.    if (IconHandlerData)
  249.    {
  250.       if (var(MajVers) < MINHMAJVERS ||
  251.          (var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
  252.              DoExit("Version mismatch with %s",HANDLER);
  253.       *thePort = &(IconHandlerData->IconPort);
  254.    } else {
  255.       DoExit("%s reports a version mismatch",HANDLER);
  256.    }
  257.    var(Segment)  = Segment;
  258. }
  259.  
  260.  
  261. /*
  262.  *  SetVectors()
  263.  *
  264.  *  Set the Intuition library vectors for the routines we are trapping
  265.  *  to the routines specified by the handler.  Save the old routine pointers
  266.  *  for later replacement.
  267.  */
  268.  
  269. static void SetVectors()
  270. {
  271.    VAR(OldOpenWindow) =
  272.       SetFunction(IntuitionBase,&LVOOpenWindow,var(aOpenWindow));
  273.    VAR(OldSetWindowTitles) =
  274.       SetFunction(IntuitionBase,&LVOSetWindowTitles,var(aSetWindowTitles));
  275.    VAR(OldOpenScreen) =
  276.       SetFunction(IntuitionBase,&LVOOpenScreen,var(aOpenScreen));
  277. }
  278.  
  279.  
  280. /*
  281.  *  UnSetVectors()
  282.  *
  283.  *  Replace the old Intuition library vectors, but make sure that no one
  284.  *  else has changed them behind our back.  If they are not the same as
  285.  *  what we set them to originally, then put back the ones that we found,
  286.  *  and return an error status.
  287.  */
  288.  
  289. static int UnSetVectors()
  290. {
  291.    long NewOpenWindow;
  292.    long NewSetWindowTitles;
  293.    long NewOpenScreen;
  294.    int status = TRUE;
  295.  
  296.    NewOpenWindow = SetFunction(IntuitionBase,&LVOOpenWindow,VAR(OldOpenWindow));
  297.    NewSetWindowTitles =
  298.       SetFunction(IntuitionBase,&LVOSetWindowTitles,VAR(OldSetWindowTitles));
  299.    NewOpenScreen = SetFunction(IntuitionBase,&LVOOpenScreen,VAR(OldOpenScreen));
  300.    if (NewOpenWindow      != (long) var(aOpenWindow) ||
  301.        NewSetWindowTitles != (long) var(aSetWindowTitles) ||
  302.        NewOpenScreen      != (long) var(aOpenScreen))
  303.    {
  304.       SetFunction(IntuitionBase,&LVOOpenWindow,NewOpenWindow);
  305.       SetFunction(IntuitionBase,&LVOSetWindowTitles,NewSetWindowTitles);
  306.       SetFunction(IntuitionBase,&LVOOpenScreen,NewOpenScreen);
  307.       status = FALSE;
  308.    }
  309.    return(status);
  310. }
  311.  
  312.  
  313. /*
  314.  *  SetVariables()
  315.  *
  316.  *  The IconHandlerData structure is used to allow the loading program to
  317.  *  set up variables needed by the handler (like Intuitionbase, etc.).  This
  318.  *  keeps the handler code to a minimum.  The loader retains pointers to the
  319.  *  linked lists, in case it needs to free memory on behalf of the handler.
  320.  */
  321.  
  322. void SetVariables(thePort)
  323. struct MsgPort *thePort;
  324. {
  325.    VAR(IntuitionBase) = IntuitionBase;
  326.    VAR(SysBase)       = SysBase;
  327.    VAR(FirstDefine)   = FirstDefine;
  328.    VAR(FirstProgram)  = FirstProgram;
  329.    VAR(ProgramAny)    = ProgramAny;
  330. }
  331.  
  332.  
  333. /*
  334.  *  GetVariables()
  335.  *
  336.  *  Look up the values stored in the IconHandlerData structure.  The 
  337.  *  Intuition library already was opened, and we will need to close it.
  338.  *  The data in the linked lists may need to be freed.
  339.  */
  340.  
  341. void GetVariables(thePort)
  342. struct MsgPort *thePort;
  343. {
  344.    IconHandlerData = (struct IconHandlerInfo *)thePort;
  345.    IntuitionBase = VAR(IntuitionBase);
  346.    FirstDefine   = VAR(FirstDefine);
  347.    FirstProgram  = VAR(FirstProgram);
  348.    ProgramAny    = VAR(ProgramAny);
  349.    Segment       = var(Segment);
  350. }
  351.  
  352.  
  353. /*
  354.  *  SetIcons()
  355.  *
  356.  *  For each window in the list of initial windows
  357.  *    Get the autoiconify flag and remove it from the icon
  358.  *    Set the given window to the specified icon
  359.  *    If autoiconify was set
  360.  *      Iconify the window and replace the autoiconify flag
  361.  */
  362.  
  363. static void SetIcons(InitIcon,i)
  364. struct NeedsIcon InitIcon[MAXICONS];
  365. short i;
  366. {
  367.    ULONG AutoIconify; 
  368.    
  369.    while (i--)
  370.    {
  371.       AutoIconify = InitIcon[i].Icon->Flags & WI_AUTOICONIFY;
  372.       InitIcon[i].Icon->Flags -= AutoIconify;
  373.       wSetIcon(InitIcon[i].Window,InitIcon[i].Icon);
  374.       if (AutoIconify)
  375.       {
  376.          wIconify(InitIcon[i].Window);
  377.          InitIcon[i].Icon->Flags |= AutoIconify;
  378.       }
  379.    }
  380. }
  381.  
  382.  
  383. /*
  384.  *  SetInitialIcons()
  385.  *
  386.  *  Forbid() so that nothing happens while we're looking at the lists
  387.  *  Start with the first screen of intutition
  388.  *  While there are more screens to check
  389.  *    Start with the screen's first window
  390.  *    While there are more windows to check
  391.  *      Get the port used by the window
  392.  *      If it has a port, and the port has a signal-taks, and the port's
  393.  *        action is to signal the task, then get the name of the process
  394.  *        that owns the port
  395.  *      Otherwise
  396.  *        Use the name [NULL]
  397.  *      Find the program/screen/window combination in the list
  398.  *      If it was found and ther eis more room in the list
  399.  *        Record the window and icon so we can add it later
  400.  *      Move on to the next window
  401.  *    Move on to the next screen
  402.  *  Permit
  403.  *  If there were icons to add, then add them (we postpone the adding
  404.  *    until now since it requires wIconify-Handler to be running, but
  405.  *    we wanted to stay in the Forbid() state without interuption).
  406.  */
  407.  
  408. static void SetInitialIcons()
  409. {
  410.    struct NeedsIcon InitIcon[MAXICONS];
  411.    short i = 0;
  412.    struct Screen *theScreen;
  413.    struct Window *theWindow;
  414.    struct MsgPort *thePort;
  415.    char Program[MAXNAME];
  416.    ICONWINDOW *theIcon;
  417.    
  418.    Forbid();
  419.    theScreen = IntuitionBase->FirstScreen;
  420.    while (theScreen)
  421.    {
  422.       theWindow = theScreen->FirstWindow;
  423.       while (theWindow)
  424.       {
  425.          thePort = theWindow->UserPort;
  426.          if (thePort && thePort->mp_SigTask != NULL &&
  427.             (thePort->mp_Flags & PF_ACTION) == PA_SIGNAL)
  428.                 VAR(GetProgramName)(Program,thePort->mp_SigTask);
  429.                else
  430.                 strcpy(Program,"[NULL]");
  431.          theIcon = VAR(FindIcon)(Program,theScreen,theWindow->Title);
  432.          if (theIcon && i<MAXICONS)
  433.          {
  434.             InitIcon[i].Window = theWindow;
  435.             InitIcon[i].Icon   = &(theIcon->Icon);
  436.             i++;
  437.          }
  438.          theWindow = theWindow->NextWindow;
  439.       }
  440.       theScreen = theScreen->NextScreen;
  441.    }
  442.    Permit();
  443.    if (i) SetIcons(InitIcon,i);
  444. }
  445.  
  446.  
  447.  
  448. /*
  449.  *  StillRunning()
  450.  *
  451.  *  If we have an error message to print
  452.  *    Print it and indicate that the handler is still active
  453.  *  Clear the lists and other variables so that they are not freed during exit
  454.  */
  455.  
  456. static void StillRunning(s)
  457. char *s;
  458. {
  459.    if (s)
  460.    {
  461.       printf(s);
  462.       printf("\n%s not removed\n",program);
  463.    }
  464.    ProgramAny = NULL;
  465.    FirstProgram = NULL;
  466.    FirstDefine  = NULL;
  467.    IntuitionBase = NULL;
  468.    Segment = NULL;
  469. }
  470.  
  471.  
  472. /*
  473.  *  InstallHandler()
  474.  *
  475.  *  If there are too many arguments, exit with the USAGE message
  476.  *  Load the handler
  477.  *  If an initialization file was specified, read it
  478.  *  Otherwise try to read the default initialization file
  479.  *  If a program was specified in the init file
  480.  *    If wIconify is running
  481.  *      If wIconSetter is NOT already running
  482.  *        Add the wIconSetter port to the system list so we can find it later
  483.  *        Set the variables needed by the handler
  484.  *        Trap the Intuition library vectors used by the handler
  485.  *        Check if any existing windows need icons
  486.  *        Let the user know that wIconSetter is installed
  487.  *        Exit without freeing memory used by the handler
  488.  *  Otherwise report an appropriate message
  489.  */
  490.  
  491. static void InstallHandler(argc,argv)
  492. int argc;
  493. char **argv;
  494. {
  495.    struct MsgPort *NamedPort;
  496.  
  497.    if (argc > 2) DoExit("Usage:  '%s'",USAGE);
  498.  
  499.    LoadHandler(&NamedPort);
  500.  
  501.    if (argc == 2)
  502.       ReadInitFile(argv[1],NULL);
  503.      else
  504.       ReadInitFile(INITFILE1,INITFILE2);
  505.  
  506.    if (FirstProgram || ProgramAny)
  507.    {
  508.       if (wIconifyActive())
  509.       {
  510.          if (FindPort(PORTNAME) == NULL)
  511.          {
  512.             AddPort(NamedPort);
  513.             SetVariables(NamedPort);
  514.             SetVectors();
  515.             SetInitialIcons();
  516.             printf("%s v%d.%d.%d Installed\n",program,
  517.                var(MajVers),var(MinVers),LOADVERS);
  518.             StillRunning(NULL);
  519.          } else printf("Attempt to re-install %s!\n",program);
  520.       } else printf("wIconify not running or incompatible version\n");
  521.    } else printf("No icons specified in initialization file\n");
  522. }
  523.  
  524.  
  525. /*
  526.  *  RemoveHandler()
  527.  *
  528.  *  Retrieve the variables that the loader set up initially
  529.  *  If the versions don't match, report an error
  530.  *  Otherwise
  531.  *    If we can remove the SetFunction() traps
  532.  *       If wIconify is still active
  533.  *         Put back the trapped vectors
  534.  *         Inform the user that we can't exit (wIconify amy still be using
  535.  *         the icons that we have set up)
  536.  *       Otherwise
  537.  *         Remove the port from the system list
  538.  *         Let the user know we've been deactivated
  539.  *     Otherwise report an error
  540.  */
  541.  
  542. static void RemoveHandler(NamedPort)
  543. struct MsgPort *NamedPort;
  544. {
  545.    GetVariables(NamedPort);
  546.    if (var(MinLoadVers) > LOADVERS || var(MajVers) < MINHMAJVERS ||
  547.       (var(MajVers) == MINHMAJVERS && var(MinVers) < MINHMINVERS))
  548.          StillRunning("Loader version mismatch");
  549.    else
  550.    {
  551.       if (UnSetVectors())
  552.       {
  553.          if (wIconifyActive())
  554.          {
  555.             SetVectors();
  556.             StillRunning("Can't cancel wIconSetter while wIconify is active");
  557.          } else {
  558.             RemPort(NamedPort);
  559.             printf("%s removed\n",program);
  560.          }
  561.       } else StillRunning("SetFunction vectors have been changed!");
  562.    }
  563. }
  564.  
  565.  
  566. /*
  567.  *  main()
  568.  *
  569.  *  Open the necessary libraries
  570.  *  Look in the system list to see if wIconSetter is already running
  571.  *  If not running, try to install the handler,
  572.  *  Otherwise try to cancel the handler
  573.  */
  574.  
  575. void main(argc,argv)
  576. int argc;
  577. char **argv;
  578. {
  579.    struct MsgPort *NamedPort;
  580.  
  581.    CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
  582.    CheckLibOpen(&GfxBase,"graphics.library",GRAPHICS_REV);
  583.  
  584.    NamedPort = FindPort(PORTNAME);
  585.    if (NamedPort == NULL)
  586.       InstallHandler(argc,argv);
  587.      else
  588.       RemoveHandler(NamedPort);
  589.    DoExit(NULL);
  590. }
  591.